package tt.dz.order.service.drools;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.ReleaseId;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import tt.dz.order.pojo.ActivityRule;
import tt.dz.order.pojo.OrderItem;
import tt.dz.order.util.OrderConstant.UserType;
import tt.dz.order.vo.OrderBaseData;

/**
 * @Title: 活动规则(drools规则)服务工具类
 * @author zhoutian   
 * @date 2015-11-17
 */
//@Component pengyu modify 临时屏蔽
public class ActivityRuleService {
	private static Logger log = LoggerFactory.getLogger(ActivityRuleService.class);
	
	//用于创建KieSession对象实例
	private KieContainer kc = null;
	
	public ActivityRuleService() {}
	
	public void init() {
		KieServices ks = KieServices.Factory.get();        
        KieFileSystem kfs = ks.newKieFileSystem();        
        ReleaseId releaseId = ks.newReleaseId( "www.dz.tt", "activityRules", "1.0-SNAPSHOT" );        
        KieBuilder kieBuilder = ks.newKieBuilder( kfs );        
        kfs.generateAndWritePomXML( releaseId );
        kfs.delete("dzActivityRules");
        //获取所有的活动规则
        List<ActivityRule> activityRules = ActivityRule.getAllRules();
        if(activityRules != null && !activityRules.isEmpty()){
        	int rulesSize = 0;
        	StringBuilder rulesStr = new StringBuilder();
        	rulesStr.append("package tt.dz.order.service.drools\r\n");
        	rulesStr.append("import tt.dz.order.vo.OrderBaseData;\r\n");
        	rulesStr.append("import tt.dz.order.pojo.OrderItem;\r\n");
        	rulesStr.append("import tt.dz.order.util.AmountUtil;\r\n");
        	rulesStr.append("import java.math.BigDecimal;\r\n");
        	for(ActivityRule rule : activityRules){
        		String serviceNo = rule.getServiceNo();
        		String serviceProviderCode = rule.getServiceProviderCode();
        		String ruleName = rule.getRuleName();
        		Integer salience = rule.getSalience();
        		String startDate = rule.getStartDate();
        		String endDate = rule.getEndDate();
        		String conditionalExpression = rule.getConditionalExpression();
        		String bizExpression = rule.getBizExpression();
        		if(StringUtils.isNotBlank(bizExpression)){
        			rulesStr.append("rule ").append("\"").append(ruleName).append("\"").append("\r\n");
        			rulesStr.append("    no-loop true").append("\r\n");
        			if(salience != null){
        				rulesStr.append("    salience ").append(salience).append("\r\n");
        			}
        			if(StringUtils.isNotBlank(startDate)){
        				rulesStr.append("    date-effective ").append("\"").append(startDate).append("\"").append("\r\n");
        			}
        			if(StringUtils.isNotBlank(endDate)){
        				rulesStr.append("    date-expires ").append("\"").append(endDate).append("\"").append("\r\n");
        			}
        			rulesStr.append("    when").append("\r\n");
        			rulesStr.append("        ").append("$obd : OrderBaseData( serviceNo == \"").append(serviceNo).append("\",").append(" serviceProviderCode == \"").append(serviceProviderCode).append("\" )").append("\r\n");
        			rulesStr.append("        ").append("$oItem : OrderItem( serviceNo == \"").append(serviceNo).append("\",").append(" serviceProvider == \"").append(serviceProviderCode).append("\" )").append("\r\n");
        			if(StringUtils.isNotBlank(conditionalExpression)){
            			rulesStr.append("        ").append(conditionalExpression).append("\r\n");
        			}
        			rulesStr.append("    then").append("\r\n");
        			rulesStr.append("        ").append(bizExpression).append("\r\n");
        			rulesStr.append("end").append("\r\n\r\n");
        			rulesSize++;            		
        		}
        	}
        	if(rulesSize > 0){
    			byte[] rulesBytes = null;
				try {
					log.info("规则代码:" + rulesStr.toString());
					rulesBytes = rulesStr.toString().getBytes("utf-8");
				} catch (UnsupportedEncodingException e) {
					log.error("将规则字符串转换为bytes时出错，rulesStr:" + rulesStr, e);
					return;
				}
				//将活动规则字符串写入KieFileSystem
        		kfs.write( ks.getResources().newByteArrayResource(rulesBytes).setResourceType( ResourceType.DRL ).setSourcePath( "dzActivityRules/ActivityRules.drl" ));
            	//如果规则不为空，对所有规则进行编译
                kieBuilder.buildAll();
                //构建KieContainer对象实例
                kc = ks.newKieContainer( releaseId );
        	}
        }
	}
	
	/**
	 * 重新构建KieContainer对象实例
	 */
	public void reBuildContainer(){
		//进行重新编译规则，构建对象
		init();
	}
	
	/**
	 * 进行规则计算(针对单个orderBaseData)
	 * @param orderBaseData
	 */
	public OrderItem caculate(OrderBaseData orderBaseData){
		//使用OrderBaseData对象创建OrderItem对象
		OrderItem orderItem = new OrderItem(orderBaseData);
		KieSession ksession = null;
		try {
			if(kc != null){
				//进行计算
				ksession = kc.newKieSession();
				//ksession.setGlobal("orderItem", orderItem);
				ksession.insert(orderBaseData);
				ksession.insert(orderItem);
				ksession.fireAllRules();
			}
		} finally {
			if(ksession != null){
				ksession.dispose();
			}
		}
		return orderItem;
	}
	
	/**
	 * 进行规则计算(针对一个订单里的所有订单项进行整体计算)
	 * @param orderBaseDatas
	 */
	public List<OrderItem> caculate(List<OrderBaseData> orderBaseDatas){
		/*
		//对OrderBaseData按照服务编号进行排序
		Collections.sort(orderBaseDatas, new Comparator<OrderBaseData>(){
			@Override
			public int compare(OrderBaseData o1, OrderBaseData o2) {
				return Integer.valueOf(o1.getServiceNo()) - Integer.valueOf(o2.getServiceNo());
			}
		});
		*/

		List<OrderItem> orderItems = new ArrayList<OrderItem>(orderBaseDatas.size());
		KieSession ksession = null;
		try {
			if(kc != null){
				//进行计算
				ksession = kc.newKieSession();
			}
			for(OrderBaseData orderBaseData : orderBaseDatas){
				//使用OrderBaseData对象创建OrderItem对象
				OrderItem orderItem = new OrderItem(orderBaseData);
				orderItem.setOrderBaseData(orderBaseData);
				orderItems.add(orderItem);
					if(ksession != null&&!orderBaseData.getUserType().equals(String.valueOf(UserType.offline_customer.value()))){
						//如果不是现金卡用户，则可以进行活动规则计算
						ksession.insert(orderBaseData);
						ksession.insert(orderItem);
					}
			}
		} finally {
			if(ksession != null){
				ksession.fireAllRules();
				ksession.dispose();
			}
		}
		return orderItems;
	}
}
